﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using NetFrameworkExtensions.Collections;

namespace NetFrameworkExtensions
{
  public struct LazyThreadSafeField<T>
  {
    private object threadLock;
    private bool isNonAssigned;
    private T value;
    private Func<T> initializer;

    public LazyThreadSafeField(object threadLock, Func<T> initializer) : this()
    {
      if (threadLock == null) throw new ArgumentNullException("threadLock");
      if (initializer == null) throw new ArgumentNullException("initializer");
      this.threadLock = threadLock;
      this.initializer = initializer;
      isNonAssigned = true;
      value = default(T);
    }

    public LazyThreadSafeField(T value) : this()
    {
      threadLock = null;
      initializer = null;
      isNonAssigned = false;
      this.value = value;
    }

    public T Value
    {
      get
      {
        if (isNonAssigned)
        {
          lock (threadLock)
          {
            if (isNonAssigned)
            {
              var localValue = initializer();
              Thread.MemoryBarrier();
              value = localValue;
              isNonAssigned = false;
            }
          }
          
        }
        return value;
      }
      set
      {
        this.value = value;
        isNonAssigned = false;
      }
    }

    public bool IsAssigned
    {
      get { return !isNonAssigned; }
    }
  }
}
